package references

import (
	"go_gvm_mini/instructions/base"
	"go_gvm_mini/rtda"
	"go_gvm_mini/rtda/heap"
)

type ATHROW struct {
	base.NoOperandsInstruction
}

func (al *ATHROW) Execute(jFrame *rtda.JFrame) {
	ex := jFrame.OperandStack().PopRef()
	if ex == nil {
		panic("java.lang.NullPointerException")
	}
	jThread := jFrame.JThread()
	if findAndGotoExceptionHandler(jThread, ex) {

	}
}

func findAndGotoExceptionHandler(jThread *rtda.JThread, ex *heap.Object) bool {
	for {
		jFrame := jThread.CurrentJFrame()
		pc := jFrame.NextPC() - 1

		handlerPC := jFrame.Method().FindExceptionHandler(ex.Class(), pc)
		if handlerPC > 0 {
			stack := jFrame.OperandStack()
			stack.Clear()
			stack.PushRef(ex)
			jFrame.SetNextPC(handlerPC)
			return true
		}
		jThread.PopJFrame()
		if jThread.IsStackEmpty() {
			break
		}
	}
	return false
}
